﻿using JNPF.Basics.Logic;
using JNPF.Basics.Logic.Common.Login;
using JNPF.Basics.Models;
using JNPF.Basics.Models.Common.Model;
using JNPF.Data.Util;
using JNPF.Utils;
using JNPF.Utils.Controller;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Net.Http;
using System.Threading.Tasks;

namespace JNPF.Basics.Controller.Common
{
    /// <summary>
    /// 公共接口
    /// 版 本：V3.0.0
    /// 版 权：引迈信息技术有限公司（https://www.jnpfsoft.com）
    /// 作 者：JNPF开发平台组
    /// 日 期：2020.09.01
    /// </summary>
    [Route("api/Common/[controller]")]
    public class LoginController : BaseApiController
    {
        private UserBll userBll = new UserBll();
        private UserRelationBll userRelationBll = new UserRelationBll();
        private OrganizeBll organizeBll = new OrganizeBll();
        private PositionBll positionBll = new PositionBll();
        private SysConfigBll sysConfigBll = new SysConfigBll();
        private LoginBll loginBll = new LoginBll();
        private UserOnlineBll userOnlineBll = new UserOnlineBll();

        #region Get
        /// <summary>
        /// 获取用户登录信息(菜单、权限等)
        /// </summary>
        /// <returns></returns>
        [HttpGet("CurrentUser")]
        public async Task<ResponseResult> GetCurrentUser()
        {
            var sysConfigInfo = await sysConfigBll.GetInfo("SysConfig");
            var userInfo = UserProvider.Instance.Get();
            var LoginCurrentUserModel = await loginBll.GetAuthorize();
            var loginCurrentUserOutput = this.LoginCurrentUser(LoginCurrentUserModel, userInfo, sysConfigInfo);
            return Success(loginCurrentUserOutput);
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <returns></returns>
        [HttpGet("Logout")]
        public ResponseResult Logout()
        {
            var userProvider = new UserProvider();
            if (userProvider.Get() != null)
                userProvider.Remove();
            return Success("注销成功");
        }
        #endregion

        #region Post
        /// <summary>
        /// 用户登录
        /// </summary>
        /// <returns></returns>
        [HttpPost("Login")]
        [AllowAnonymous]
        public async Task<ResponseResult> Login([FromBody] LoginLoginInput input)
        {
            try
            {
                var userInfo = new UserInfo();
                #region 多租户
                if (ConfigurationKey.MultiTenancy)
                {
                    var tenantAccount = input.account.Split('@');
                    var tenantDbName = await this.GetTenantDbName(tenantAccount[0]);
                    userInfo.TenantId = tenantAccount[0];
                    userInfo.TenantDbType = "SqlServer";
                    userInfo.TenantDbConnectionString = tenantDbName;
                    WebHelper.HttpAddItems("TenantId", userInfo.TenantId);
                    WebHelper.HttpAddItems("TenantDbType", userInfo.TenantDbType);
                    WebHelper.HttpAddItems("TenantDbConnectionString", userInfo.TenantDbConnectionString);
                    if (tenantAccount.Length == 1)
                        input.account = "admin";
                    else
                        input.account = tenantAccount[1];
                }
                #endregion
                var sysConfigInfo = await sysConfigBll.GetInfo("SysConfig");
                var userEntity = await userBll.CheckLogin(input.account.Trim(), input.password.Trim());
                userInfo.IsAdministrator = userEntity.IsAdministrator.ToBool();
                userInfo.UserId = userEntity.Id;
                userInfo.UserAccount = userEntity.Account;
                userInfo.UserName = userEntity.RealName;
                userInfo.UserIcon = userEntity.HeadIcon;
                userInfo.OrganizeId = userEntity.OrganizeId;
                userInfo.ManagerId = userEntity.ManagerId;
                userInfo.SubOrganizeIds = await this.GetSubOrganizeIds(userEntity.OrganizeId, userEntity.IsAdministrator.ToBool());
                userInfo.SubordinateIds = await this.GetSubordinateId(userEntity.Id);
                userInfo.PositionIds = await this.GetPositionId(userEntity.Id);
                userInfo.RoleIds = await this.GetRoleId(userEntity.Id);
                #region 安全验证
                if (sysConfigInfo.SingleLogin == "2")
                {
                    var userOnlines = (await userOnlineBll.GetList()).Find(x => x.userAccount == input.account);
                    if (userOnlines.IsNotEmptyOrNull())
                    {
                        return Error("此账号已在其他地方登陆");
                    }
                }
                if (sysConfigInfo.whitelistSwitch == 1)
                {
                    var IPList = sysConfigInfo.whitelistIP.Split(",").ToList();
                    if (!IPList.Contains(Net.Ip))
                    {
                        return Error("此IP未在白名单中，请联系管理员");
                    }
                }
                #endregion
                userInfo.LoginTime = DateTime.Now;
                userInfo.LoginIPAddress = Net.Ip;
                userInfo.LoginIPAddressName = Net.GetLocation(userInfo.LoginIPAddress);
                userInfo.LoginPlatForm = Net.UserAgent;
                userInfo.PrevLoginTime = userEntity.PrevLogTime;
                userInfo.PrevLoginIPAddress = userEntity.PrevLogIP;
                userInfo.PrevLoginIPAddressName = Net.GetLocation(userInfo.PrevLoginIPAddress);
                userInfo.OverdueTime = TimeSpan.FromMinutes(double.Parse(sysConfigInfo.TokenTimeout));
                userInfo.PortalId = userEntity.PortalId;
                await LogBll.Instance.WriteLogAsync(userEntity.Id, userEntity.RealName + "/" + userEntity.Account, "登录成功");
                UserProvider.Instance.Add(userInfo);
                var output = new LoginLoginOutput();
                if (Net.isMobileBrowser)
                {
                    output.token = userInfo.Id;
                }
                else
                {
                    output.token = userInfo.Id;
                    output.theme = userEntity.Theme == null ? "W-001" : userEntity.Theme;
                }
                return Success(output);
            }
            catch (Exception ex)
            {
                LogFactory.GetLogger().Error("登录错误:" + ex);
                return Error(ex.InnerException == null ? ex.Message : ex.InnerException.Message);
            }
            finally
            {
                WebHelper.HttpRemoveItems("TenantId");
                WebHelper.HttpRemoveItems("TenantDbType");
                WebHelper.HttpRemoveItems("TenantDbConnectionString");
            }
        }

        /// <summary>
        /// 锁屏解锁登录
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("LockScreen")]
        public async Task<ResponseResult> LockScreen([FromBody] LoginLockScreenInput input)
        {
            try
            {
                var userEntity = await userBll.CheckLogin(input.account.Trim(), input.password.Trim());
                return Success("验证成功");
            }
            catch (Exception ex)
            {
                return Error(ex.InnerException.Message);
            }
        }
        #endregion

        #region private Method
        /// <summary>
        /// 下属机构
        /// </summary>
        /// <param name="organizeId"></param>
        /// <param name="isAdmin"></param>
        /// <returns></returns>
        private async Task<string[]> GetSubOrganizeIds(string organizeId, bool isAdmin)
        {
            var data = await organizeBll.GetList();
            if (!isAdmin)
            {
                data = data.TreeChildNode(organizeId, t => t.Id, t => t.ParentId);
            }
            return data.Select(m => m.Id).ToArray();
        }
        /// <summary>
        /// 获取下属
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task<string[]> GetSubordinateId(string userId)
        {
            var data = await userBll.GetListByManagerId(userId);
            return data.Select(m => m.Id).ToArray();
        }
        /// <summary>
        /// 获取岗位
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task<string[]> GetPositionId(string userId)
        {
            var data = await userRelationBll.GetListByUserId(userId);
            return data.FindAll(m => m.ObjectType == "Position").Select(m => m.ObjectId).ToArray();
        }
        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task<string[]> GetRoleId(string userId)
        {
            var data = await userRelationBll.GetListByUserId(userId);
            return data.FindAll(m => m.ObjectType == "Role").Select(m => m.ObjectId).ToArray();
        }
        /// <summary>
        /// 登录信息
        /// </summary>
        /// <param name="userInfo">回话信息</param>
        /// <param name="systemInfo">系统信息</param>
        /// <returns></returns>
        private object GetUserInfo(UserInfo userInfo, BaseSystemInfo systemInfo)
        {
            var dictionary = new Dictionary<string, object>();
            dictionary.Add("userId", userInfo.UserId);
            dictionary.Add("userAccount", userInfo.UserAccount);
            dictionary.Add("userName", userInfo.UserName);
            dictionary.Add("headIcon", "/api/Common/Image/userAvatar/" + userInfo.UserIcon);
            dictionary.Add("gender", userInfo.UserGender);
            dictionary.Add("organizeId", userInfo.OrganizeId);
            dictionary.Add("organizeName", GetCompany(userInfo.OrganizeId).Result);
            dictionary.Add("positionIds", GetPosition(userInfo.PositionIds));
            dictionary.Add("prevLogin", systemInfo.LastLoginTimeSwitch == "1" ? 1 : 0);
            dictionary.Add("prevLoginTime", userInfo.PrevLoginTime);
            dictionary.Add("prevLoginIPAddress", userInfo.PrevLoginIPAddress);
            dictionary.Add("prevLoginIPAddressName", userInfo.PrevLoginIPAddressName);
            dictionary.Add("departmentId", userInfo.OrganizeId);
            dictionary.Add("departmentName", organizeBll.GetName(userInfo.OrganizeId));
            dictionary.Add("portalId", userInfo.PortalId);
            return dictionary;
        }
        /// <summary>
        /// 用户登录信息结构转换
        /// </summary>
        /// <param name="input">数据源</param>
        /// <param name="userInfo">数据源</param>
        /// <param name="systemInfo">数据源</param>
        /// <returns></returns>
        private LoginCurrentUserOutput LoginCurrentUser(LoginCurrentUserModel input, UserInfo userInfo, BaseSystemInfo systemInfo)
        {
            var loginCurrentUserOutput = new LoginCurrentUserOutput();
            loginCurrentUserOutput.menuList = input.moduleList.MapToList<MenuModel>().FindAll(t => t.category == "Web").ToTree("-1");
            var permissionList = new List<PermissionModel>();
            input.moduleList.ForEach(menu =>
            {
                var permissionModel = new PermissionModel();
                permissionModel.modelId = menu.Id;
                permissionModel.moduleName = menu.FullName;
                permissionModel.button = input.buttonList.FindAll(t => t.ModuleId.Equals(menu.Id)).MapToList<AuthorizeModuleButtonModelNew>();
                permissionModel.column = input.columnList.FindAll(t => t.ModuleId.Equals(menu.Id)).MapToList<AuthorizeModuleColumnModelNew>();
                permissionModel.resource = input.resourceList.FindAll(t => t.ModuleId.Equals(menu.Id)).MapToList<AuthorizeModuleResourceModelNew>();
                permissionList.Add(permissionModel);
            });
            loginCurrentUserOutput.permissionList = permissionList;
            loginCurrentUserOutput.userInfo = this.GetUserInfo(userInfo, systemInfo);
            return loginCurrentUserOutput;
        }
        /// <summary>
        /// 获取公司名称
        /// </summary>
        /// <param name="OrganizeId">id</param>
        /// <returns></returns>
        private async Task<string> GetCompany(string OrganizeId)
        {
            var data = await organizeBll.GetInfo(OrganizeId);
            if (data == null || string.IsNullOrEmpty(data.Category))
            {
                return "";
            }
            if (data.Category.Equals("department"))
            {
                return await GetCompany(data.ParentId);
            }
            else
            {
                return data.FullName;
            }
        }
        /// <summary>
        /// 获取当前用户岗位信息
        /// </summary>
        /// <param name="PositionIds"></param>
        /// <returns></returns>
        private List<object> GetPosition(string[] PositionIds)
        {
            List<object> list = new List<object>();
            PositionIds.ToList().ForEach(x => list.Add(new { id = x, name = positionBll.GetName(x) }));
            return list;
        }
        /// <summary>
        /// 获取租户数据库
        /// </summary>
        /// <param name="enCode">租户号</param>
        /// <returns></returns>
        private async Task<string> GetTenantDbName(string enCode)
        {
            var interFace = ConfigurationHelper.GetValue("MultiTenancyDBInterFace");
            var requestApi = interFace + enCode;
            var response = await new HttpClient().GetAsync(requestApi);
            var responseResult = await response.Content.ReadAsStringAsync();
            var result = responseResult.ToObject();
            if (result["code"].ToInt() != 200)
            {
                throw new Exception(result["msg"].ToString());
            }
            if (result["data"]["dbName"].IsNotEmptyOrNull())
            {
                return result["data"]["dbName"].ToString();
            }
            else
            {
                return result["data"]["dotnet"].ToString();
            }
        }
        #endregion
    }
}
